探索一次Golang程序unexpected fault fatal error
众所周知,在go协程中操作线程不安全的对象是犯了大忌。但是讲道理,上层的recover应该能hold住大部分的情况,没想到这次居然导致整个程序挂了。虽然代码不是我写的,为了排除其他潜在的隐患,于是我进行了一波探索与模拟。程序退出前,控制台日志输出大致如下:
1 | unexpected fault address 0x |
对于能挂掉整个程序的协程,怀疑是协程中有协程没recover住panic?检查了波代码,并没有出现这样的情况。看了堆栈的信息是定位到了一行append上,append调用了runtime包下的slice.go中的growslice,growSlice又调用了memmove才导致了如上的错误,于是就把关注点集中到了memmove上。memmove是汇编实现的,为了能调用汇编代码,使用了go:linkname去链接这个汇编函数。
1 | // go:linkname memmove runtime.memmove |
这样就可以在测试代码中调用memmove了,接下来写一波测试代码模拟并发调用的情况。
1 | func TestMemmove(t *testing.T) { |
果然不出所料,recover并没有recover住,程序直接fatal error。可见golang runtime在对内存进行一些wild的操作也是无法recover的。由于业务代码较多,就用了上述的方式模拟。
切记在并发操作中一定要关注线程安全问题。
探索一次Golang程序unexpected fault fatal error
https://www.huihongcloud.com/2021/07/31/go/探索一次Golang程序unexpected fault fatal error/